package server.commands;

import client.MapleCharacter;
import client.MapleCharacterUtil;
import client.MapleClient;
import client.MapleDisease;
import client.MapleStat;
import client.SkillFactory;
import client.anticheat.ReportType;
import client.inventory.Item;
import client.inventory.ItemFlag;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryIdentifier;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import constants.GameConstants;
import constants.ItemConstants;
import tools.SearchGenerator;
import handling.channel.ChannelServer;
import handling.world.CheaterData;
import handling.world.World;
import java.io.Serializable;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import scripting.NPCScriptManager;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MaplePortal;
import server.MapleSquad.MapleSquadType;
import server.life.MapleLifeFactory;
import server.life.MapleMonster;
import server.life.MapleMonsterInformationProvider;
import server.life.MobSkillFactory;
import server.life.MonsterGlobalDropEntry;
import server.maps.MapleMap;
import server.maps.MapleMapItem;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import server.quest.MapleQuest;
import server.shops.MapleShopFactory;
import tools.FileoutputUtil;
import tools.Pair;
import tools.StringUtil;
import tools.packet.CField;
import tools.packet.CField.NPCPacket;
import tools.packet.CWvsContext;

/**
 *
 * @author Emilyx3
 */
public class InternCommand {

    public static PlayerGMRank getPlayerLevelRequired() {
        return PlayerGMRank.INTERN;
    }

    public static class 隱藏 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (c.getPlayer().isHidden()) {
                c.getPlayer().dispelBuff(9001004);
                c.getPlayer().dropMessage(-5, "隱藏已關閉。");
                MapleItemInformationProvider.getInstance().getItemEffect(2100069).applyTo(c.getPlayer());
                c.getSession().write(CWvsContext.InfoPacket.getStatusMsg(2100069));
            } else {
                SkillFactory.getSkill(9001004).getEffect(1).applyTo(c.getPlayer());
                c.getPlayer().dropMessage(-5, "隱藏已開啟。");
            }
            return 0;
        }
    }

    public static class 隱藏聊天可見 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (c.getPlayer().isHiddenChatCanSee()) {
                c.getPlayer().setHiddenChatCanSee(false);
                c.getPlayer().dropMessage(6, "當前隱藏狀態時聊天訊息玩家可見性：不可見");
            } else {
                c.getPlayer().setHiddenChatCanSee(true);
                c.getPlayer().dropMessage(6, "當前隱藏狀態時聊天訊息玩家可見性：可見");
            }
            return 0;
        }
    }

    public static class 治愈 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            c.getPlayer().getStat().heal(c.getPlayer());
            c.getPlayer().dispelDebuffs();
            return 0;
        }
    }

    public static class 治愈全圖 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleCharacter player = c.getPlayer();
            for (MapleCharacter mch : player.getMap().getCharacters()) {
                if (mch != null) {
                    mch.getStat().heal(mch);
                    mch.dispelDebuffs();
                }
            }
            return 1;
        }
    }

    public static class 臨時封號 extends CommandExecute {

        protected boolean ipBan = false;
        private final String[] types = {"外掛", "BOT", "AD", "HARASS", "CURSE", "SCAM", "MISCONDUCT", "SELL", "ICASH", "TEMP", "GM", "IPROGRAM", "MEGAPHONE"};

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 4) {
                c.getPlayer().dropMessage(6, splitted[0] + " <玩家名稱> <理由> <時間(小時)>");
                StringBuilder s = new StringBuilder("臨時封號理由: ");
                for (int i = 0; i < types.length; i++) {
                    s.append(i + 1).append(" - ").append(types[i]).append(", ");
                }
                c.getPlayer().dropMessage(6, s.toString());
                return 0;
            }
            final MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[1]);
            final int reason = Integer.parseInt(splitted[2]);
            final int numHour = Integer.parseInt(splitted[3]);

            final Calendar cal = Calendar.getInstance();
            cal.add(Calendar.HOUR, numHour);
            final DateFormat df = DateFormat.getInstance();

            if (victim == null || reason < 0 || reason >= types.length) {
                c.getPlayer().dropMessage(6, "無法找到玩家或者理由是無效的, 輸入" + splitted[0] + "查看可用理由");
                return 0;
            }
            victim.tempban("因 " + types[reason] + " 被 " + c.getPlayer().getName() + " 臨時封號", cal, reason, ipBan);
            c.getPlayer().dropMessage(6, "玩家 " + splitted[1] + " 被臨時封號到 " + df.format(cal.getTime()));
            return 1;
        }
    }

    public static class 封號 extends CommandExecute {

        protected boolean hellban = false, ipBan = false;

        private String getCommand() {
            if (hellban) {
                return "匿名封號";
            } else if (ipBan) {
                return "封IP";
            } else {
                return "封號";
            }
        }

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 3) {
                c.getPlayer().dropMessage(5, splitted[0] + " <玩家名稱> <理由>");
//                c.getPlayer().dropMessage(5, "If you want to consider this ban as an autoban, set the reason \"AutoBan\"");
                return 0;
            }
            StringBuilder sb = new StringBuilder();
            if (hellban) {
                sb.append(splitted[1]).append("被封號: ").append(StringUtil.joinStringFrom(splitted, 2));
            } else {
                sb.append(c.getPlayer().getName()).append(" 對 ").append(splitted[1]).append(" 進行封號處理: ").append(StringUtil.joinStringFrom(splitted, 2));
            }
            MapleCharacter target = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[1]);
            if (target != null) {
                if ((c.getPlayer().getGMLevel() > target.getGMLevel() || c.getPlayer().isAdmin()) && !target.getClient().isGM() && !target.isAdmin()) {
                    //sb.append(" (IP: ").append(target.getClient().getSessionIPAddress()).append(")");
                    if (target.ban(sb.toString(), hellban || ipBan, false, hellban)) {
                        c.getPlayer().dropMessage(6, "[" + getCommand() + "] " + splitted[1] + " 已經被封號");
                        return 1;
                    } else {
                        c.getPlayer().dropMessage(6, "[" + getCommand() + "] 封號失敗");
                        return 0;
                    }
                } else {
                    c.getPlayer().dropMessage(6, "[" + getCommand() + "] 無法封GM...");
                    return 1;
                }
            } else {
                if (MapleCharacter.ban(splitted[1], sb.toString(), false, c.getPlayer().isAdmin() ? 250 : c.getPlayer().getGMLevel(), hellban)) {
                    c.getPlayer().dropMessage(6, "[" + getCommand() + "] " + splitted[1] + " 已經被離線封號");
                    return 1;
                } else {
                    c.getPlayer().dropMessage(6, "[" + getCommand() + "] " + splitted[1] + "封號失敗");
                    return 0;
                }
            }
        }
    }

    public static class 下線 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <玩家名稱> ([玩家名稱] [玩家名稱]...)");
                return 0;
            }
            MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[splitted.length - 1]);
            if (victim != null && c.getPlayer().getGMLevel() >= victim.getGMLevel()) {
                victim.getClient().getSession().close(true);
                victim.getClient().disconnect(true, false);
                return 1;
            } else {
                c.getPlayer().dropMessage(6, "受害者不存在或不在線上。");
                return 0;
            }
        }
    }

    public static class 殺 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleCharacter player = c.getPlayer();
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <玩家名稱> ([玩家名稱] [玩家名稱]...)");
                return 0;
            }
            MapleCharacter victim = null;
            for (int i = 1; i < splitted.length; i++) {
                try {
                    victim = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[i]);
                } catch (Exception e) {
                    c.getPlayer().dropMessage(6, "沒找到受害者 " + splitted[i]);
                }
                if (player.allowedToTarget(victim) && player.getGMLevel() >= victim.getGMLevel()) {
                    victim.getStat().setHp((short) 0, victim);
                    victim.getStat().setMp((short) 0, victim);
                    victim.updateSingleStat(MapleStat.HP, victim.getStat().getHp());
                    victim.updateSingleStat(MapleStat.MP, victim.getStat().getMp());
                }
            }
            return 1;
        }
    }

    public static class 我在哪裡 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            c.getPlayer().dropMessage(5, "你所在的地圖為 " + c.getPlayer().getMap().toString());
            return 1;
        }
    }

    public static class 線上 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            String online = "";
            for (ChannelServer cs : ChannelServer.getAllInstances()) {
                online += cs.getPlayerStorage().getOnlinePlayers(true);
            }
            c.getPlayer().dropMessage(6, online);
            return 1;
        }
    }

    public static class 角色訊息 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <玩家名稱>");
                return 0;
            }
            final StringBuilder builder = new StringBuilder();
            final MapleCharacter other = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[1]);
            if (other == null) {
                builder.append("輸入的角色不存在...");
                c.getPlayer().dropMessage(6, builder.toString());
                return 0;
            }
            if (other.getClient().getLastPing() <= 0) {
                other.getClient().sendPing();
            }
            builder.append(MapleClient.getLogMessage(other, ""));
            builder.append(" 坐標 ").append(other.getPosition().x);
            builder.append(" /").append(other.getPosition().y);

            builder.append(" || HP : ");
            builder.append(other.getStat().getHp());
            builder.append(" /");
            builder.append(other.getStat().getCurrentMaxHp());

            builder.append(" || MP : ");
            builder.append(other.getStat().getMp());
            builder.append(" /");
            builder.append(other.getStat().getCurrentMaxMp(other.getJob()));

            builder.append(" || BattleshipHP : ");
            builder.append(other.currentBattleshipHP());

            builder.append(" || 物理攻擊力 : ");
            builder.append(other.getStat().getTotalWatk());
            builder.append(" || 魔法攻擊力 : ");
            builder.append(other.getStat().getTotalMagic());
            builder.append(" || 最大傷害 : ");
            builder.append(other.getStat().getCurrentMaxBaseDamage());
            builder.append(" || 傷害% : ");
            builder.append(other.getStat().dam_r);
            builder.append(" || BOSS攻擊力% : ");
            builder.append(other.getStat().bossdam_r);
            builder.append(" || 暴擊幾率 : ");
            builder.append(other.getStat().passive_sharpeye_rate());
            builder.append(" || 暴擊傷害 : ");
            builder.append(other.getStat().passive_sharpeye_percent());

            builder.append(" || STR : ");
            builder.append(other.getStat().getStr()).append(" + (").append(other.getStat().getTotalStr() - other.getStat().getStr()).append(")");
            builder.append(" || DEX : ");
            builder.append(other.getStat().getDex()).append(" + (").append(other.getStat().getTotalDex() - other.getStat().getDex()).append(")");
            builder.append(" || INT : ");
            builder.append(other.getStat().getInt()).append(" + (").append(other.getStat().getTotalInt() - other.getStat().getInt()).append(")");
            builder.append(" || LUK : ");
            builder.append(other.getStat().getLuk()).append(" + (").append(other.getStat().getTotalLuk() - other.getStat().getLuk()).append(")");

            builder.append(" || 經驗 : ");
            builder.append(other.getExp());
            builder.append(" || 楓幣 : ");
            builder.append(other.getMeso());

            builder.append(" || Vote Points : ");
            builder.append(other.getVPoints());
            builder.append(" || Event Points : ");
            builder.append(other.getPoints());
            builder.append(" || NX Prepaid : ");
            builder.append(other.getCSPoints(1));

            builder.append(" || 是否組隊 : ");
            builder.append(other.getParty() == null ? -1 : other.getParty().getId());

            builder.append(" || 是否交易: ");
            builder.append(other.getTrade() != null);
            builder.append(" || Latency: ");
            builder.append(other.getClient().getLatency());
            builder.append(" || PING: ");
            builder.append(other.getClient().getLastPing());
            builder.append(" || PONG: ");
            builder.append(other.getClient().getLastPong());
            builder.append(" || 連接地地址: ");
            other.getClient().DebugMessage(builder);

            c.getPlayer().dropMessage(6, builder.toString());
            return 1;
        }
    }

    public static class Cheaters extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            List<CheaterData> cheaters = World.getCheaters();
            for (int x = cheaters.size() - 1; x >= 0; x--) {
                CheaterData cheater = cheaters.get(x);
                c.getPlayer().dropMessage(6, cheater.getInfo());
            }
            return 1;
        }
    }

    public static class 去往 extends CommandExecute {

        private static final HashMap<String, Integer> gotomaps = new HashMap<>();

        static {
            gotomaps.put("專業技術村", 910001000);
            gotomaps.put("納希沙漠", 260000100);
            gotomaps.put("楓之島", 1010000);
            gotomaps.put("結婚村莊", 680000000);
            gotomaps.put("另一個水世界", 860000000);
            gotomaps.put("水之都", 230000000);
            gotomaps.put("駁船碼頭城", 541000000);
//            gotomaps.put("cwk", 610030000);
            gotomaps.put("埃德爾斯坦", 310000000);
            gotomaps.put("艾靈森林", 300000000);
            gotomaps.put("魔法森林", 101000000);
            gotomaps.put("愛里涅湖水", 101071300);
            gotomaps.put("精靈之林", 101050000);
            gotomaps.put("冰原雪域", 211000000);
            gotomaps.put("耶雷弗", 130000000);
//            gotomaps.put("florina", 120000300);
            gotomaps.put("自由市場", 910000000);
            gotomaps.put("未來之門", 271000000);
            gotomaps.put("工作場所", 180000000);
            gotomaps.put("幸福村", 209000000);
            gotomaps.put("維多利亞港", 104000000);
            gotomaps.put("弓箭手村", 100000000);
            gotomaps.put("藥靈幻境", 251000000);
            gotomaps.put("鄉村鎮", 551000000);
            gotomaps.put("墮落城市", 103000000);
//            gotomaps.put("korean", 222000000);
            gotomaps.put("神木村", 240000000);
            gotomaps.put("玩具城", 220000000);
            gotomaps.put("馬來西亞", 550000000);
            gotomaps.put("桃花仙境", 250000000);
            gotomaps.put("鯨魚號", 120000000);
            gotomaps.put("新葉城", 600000000);
//            gotomaps.put("omega", 221000000);
            gotomaps.put("天空之城", 200000000);
            gotomaps.put("萬神殿", 400000000);
            gotomaps.put("皮卡啾", 270050100);
//            gotomaps.put("phantom", 610010000);
            gotomaps.put("勇士之村", 102000000);
            gotomaps.put("瑞恩村", 140000000);
            gotomaps.put("昭和村", 801000000);
            gotomaps.put("新加坡", 540000000);
            gotomaps.put("六條岔路", 104020000);
            gotomaps.put("奇幻村", 105000000);
            gotomaps.put("楓之港", 2000000);
            gotomaps.put("綠樹村", 866000000);
            gotomaps.put("三扇門", 270000000);
            gotomaps.put("黃昏的勇士之村", 273000000);
            gotomaps.put("克林森烏德城", 301000000);
            gotomaps.put("海怒斯", 230040420);
            gotomaps.put("闇黑龍王", 240060200);
            gotomaps.put("混沌闇黑龍王", 240060201);
            gotomaps.put("格瑞芬多", 240020101);
            gotomaps.put("噴火龍", 240020401);
            gotomaps.put("殘暴炎魔", 280030100);
            gotomaps.put("混沌殘暴炎魔", 280030000);
            gotomaps.put("拉圖斯", 220080001);
            gotomaps.put("選邊站", 109020001);
            gotomaps.put("向上攀升", 109030101);
            gotomaps.put("障礙競走", 109040000);
            gotomaps.put("滾雪球", 109060000);
            gotomaps.put("江戶村", 800000000);
        }

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <地圖名>");
            } else {
                if (gotomaps.containsKey(splitted[1])) {
                    MapleMap target = c.getChannelServer().getMapFactory().getMap(gotomaps.get(splitted[1]));
                    if (target == null) {
                        c.getPlayer().dropMessage(6, "地圖不存在");
                        return 0;
                    }
                    MaplePortal targetPortal = target.getPortal(0);
                    c.getPlayer().changeMap(target, targetPortal);
                } else {
                    if (splitted[1].equals("列表")) {
                        c.getPlayer().dropMessage(6, "地圖列表: ");
                        StringBuilder sb = new StringBuilder();
                        for (String s : gotomaps.keySet()) {
                            sb.append(s).append(", ");
                        }
                        c.getPlayer().dropMessage(6, sb.substring(0, sb.length() - 2));
                    } else {
                        c.getPlayer().dropMessage(6, "指令錯誤, 使用方法: " + splitted[0] + " <地圖名>(你可以使用 " + splitted[0] + " 列表 來獲取可用地圖列表)");
                    }
                }
            }
            return 1;
        }
    }

    public static class 時鐘 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " (時間:默認60秒)");
            }
            c.getPlayer().getMap().broadcastMessage(CField.getClock(CommandProcessorUtil.getOptionalIntArg(splitted, 1, 60)));
            return 1;
        }
    }

    public static class 來這裡 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <玩家名稱>");
                return 0;
            }
            MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[1]);
            if (victim != null) {
                if (c.getPlayer().inPVP() || (!c.getPlayer().isGM() && (victim.isInBlockedMap() || victim.isGM()))) {
                    c.getPlayer().dropMessage(5, "請稍後再試");
                    return 0;
                }
                victim.changeMap(c.getPlayer().getMap(), c.getPlayer().getMap().findClosestPortal(c.getPlayer().getTruePosition()));
            } else {
                int ch = World.Find.findChannel(splitted[1]);
                if (ch < 0) {
                    c.getPlayer().dropMessage(5, "未找到");
                    return 0;
                }
                victim = ChannelServer.getInstance(ch).getPlayerStorage().getCharacterByName(splitted[1]);
                if (victim == null || victim.inPVP() || (!c.getPlayer().isGM() && (victim.isInBlockedMap() || victim.isGM()))) {
                    c.getPlayer().dropMessage(5, "請稍後再試");
                    return 0;
                }
                c.getPlayer().dropMessage(5, "受害者正在更變頻道");
                victim.dropMessage(5, "正在更變頻道");
                if (victim.getMapId() != c.getPlayer().getMapId()) {
                    final MapleMap mapp = victim.getClient().getChannelServer().getMapFactory().getMap(c.getPlayer().getMapId());
                    victim.changeMap(mapp, mapp.findClosestPortal(c.getPlayer().getTruePosition()));
                }
                victim.changeChannel(c.getChannel());
            }
            return 1;
        }
    }

    public static class 傳送 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0]);
                c.getPlayer().dropMessage(6, "用法一:(要傳送的玩家名稱) <地圖ID> (傳送點ID:默認無)");
                c.getPlayer().dropMessage(6, "用法二:<要傳送到的玩家名稱>");
                return 0;
            }
            MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[1]);
            if (victim != null && c.getPlayer().getGMLevel() >= victim.getGMLevel() && !victim.inPVP() && !c.getPlayer().inPVP()) {
                if (splitted.length == 2) {
                    c.getPlayer().changeMap(victim.getMap(), victim.getMap().findClosestSpawnpoint(victim.getTruePosition()));
                } else {
                    MapleMap target = ChannelServer.getInstance(c.getChannel()).getMapFactory().getMap(Integer.parseInt(splitted[2]));
                    if (target == null) {
                        c.getPlayer().dropMessage(6, "地圖不存在");
                        return 0;
                    }
                    MaplePortal targetPortal = null;
                    if (splitted.length > 3) {
                        try {
                            targetPortal = target.getPortal(Integer.parseInt(splitted[3]));
                        } catch (IndexOutOfBoundsException e) {
                            // noop, assume the gm didn't know how many portals there are
                            c.getPlayer().dropMessage(5, "傳送點的選擇無效");
                        } catch (NumberFormatException a) {
                            // noop, assume that the gm is drunk
                        }
                    }
                    if (targetPortal == null) {
                        targetPortal = target.getPortal(0);
                    }
                    victim.changeMap(target, targetPortal);
                }
            } else {
                try {
                    int ch = World.Find.findChannel(splitted[1]);
                    if (ch < 0) {
                        MapleMap target = c.getChannelServer().getMapFactory().getMap(Integer.parseInt(splitted[1]));
                        if (target == null) {
                            c.getPlayer().dropMessage(6, "地圖不存在");
                            return 0;
                        }
                        MaplePortal targetPortal = null;
                        if (splitted.length > 2) {
                            try {
                                targetPortal = target.getPortal(Integer.parseInt(splitted[2]));
                            } catch (IndexOutOfBoundsException e) {
                                // noop, assume the gm didn't know how many portals there are
                                c.getPlayer().dropMessage(5, "傳送點的選擇無效");
                            } catch (NumberFormatException a) {
                                // noop, assume that the gm is drunk
                            }
                        }
                        if (targetPortal == null) {
                            targetPortal = target.getPortal(0);
                        }
                        c.getPlayer().changeMap(target, targetPortal);
                    } else {
                        victim = ChannelServer.getInstance(ch).getPlayerStorage().getCharacterByName(splitted[1]);
                        c.getPlayer().dropMessage(6, "正在更變頻道, 請稍候");
                        if (victim.getMapId() != c.getPlayer().getMapId()) {
                            final MapleMap mapp = c.getChannelServer().getMapFactory().getMap(victim.getMapId());
                            c.getPlayer().changeMap(mapp, mapp.findClosestPortal(victim.getTruePosition()));
                        }
                        c.getPlayer().changeChannel(ch);
                    }
                } catch (NumberFormatException e) {
                    c.getPlayer().dropMessage(6, "出現錯誤: " + e.getMessage());
                    return 0;
                }
            }
            return 1;
        }
    }

    public static class 說 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length > 1) {
                StringBuilder sb = new StringBuilder();
                sb.append("[");
                if (!c.getPlayer().isGM()) {
                    sb.append("實習 ");
                }
                sb.append(c.getPlayer().getName());
                sb.append("] ");
                sb.append(StringUtil.joinStringFrom(splitted, 1));
                World.Broadcast.broadcastMessage(CWvsContext.broadcastMsg(c.getPlayer().isGM() ? 6 : 5, sb.toString()));
            } else {
                c.getPlayer().dropMessage(6, splitted[0] + " <內容>");
                return 0;
            }
            return 1;
        }
    }

    public static class 搜尋 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length == 2) {
                c.getPlayer().dropMessage(6, "請提供搜尋訊息");
            } else {
                boolean err = false;
                if (splitted.length == 1) {
                    err = true;
                } else {
                    String typeName = splitted[1];
                    String search = StringUtil.joinStringFrom(splitted, 2);
                    SearchGenerator.SearchType type = SearchGenerator.SearchType.valueOf(typeName);
                    if (type != SearchGenerator.SearchType.未知) {
                        if (!SearchGenerator.foundData(type.getValue(), search)) {
                            c.getPlayer().dropMessage(6, "搜尋不到此" + type.name());
                            return 0;
                        }
                        String str = SearchGenerator.searchData(type, search);
                        c.getSession().write(NPCPacket.getNPCTalk(9010000, (byte) 5, str, "", (byte) 0));
                        return 1;
                    }
                    err = true;
                }
                if (err) {
                    StringBuilder sb = new StringBuilder("");
                    for (SearchGenerator.SearchType searchType : SearchGenerator.SearchType.values()) {
                        if (searchType != SearchGenerator.SearchType.未知) {
                            sb.append(searchType.name()).append("/");
                        }
                    }
                    c.getPlayer().dropMessage(6, splitted[0] + ": <類型> <搜尋訊息>");
                    c.getPlayer().dropMessage(6, "類型:" + sb.toString());
                }
            }
            return 0;
        }
    }

    public static class WhosFirst extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            //probably bad way to do it
            final long currentTime = System.currentTimeMillis();
            List<Pair<String, Long>> players = new ArrayList<>();
            for (MapleCharacter chr : c.getPlayer().getMap().getCharactersThreadsafe()) {
                if (!chr.isIntern()) {
                    players.add(new Pair<>(MapleCharacterUtil.makeMapleReadable(chr.getName()) + (currentTime - chr.getCheatTracker().getLastAttack() > 600000 ? " (AFK)" : ""), chr.getChangeTime()));
                }
            }
            Collections.sort(players, new WhoComparator());
            StringBuilder sb = new StringBuilder("List of people in this map in order, counting AFK (10 minutes):  ");
            for (Pair<String, Long> z : players) {
                sb.append(z.left).append(", ");
            }
            c.getPlayer().dropMessage(6, sb.toString().substring(0, sb.length() - 2));
            return 0;
        }

        public static class WhoComparator implements Comparator<Pair<String, Long>>, Serializable {

            @Override
            public int compare(Pair<String, Long> o1, Pair<String, Long> o2) {
                if (o1.right > o2.right) {
                    return 1;
                } else if (Objects.equals(o1.right, o2.right)) {
                    return 0;
                } else {
                    return -1;
                }
            }
        }
    }

    public static class WhosLast extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                StringBuilder sb = new StringBuilder("whoslast [type] where type can be:  ");
                for (MapleSquadType t : MapleSquadType.values()) {
                    sb.append(t.name()).append(", ");
                }
                c.getPlayer().dropMessage(6, sb.toString().substring(0, sb.length() - 2));
                return 0;
            }
            final MapleSquadType t = MapleSquadType.valueOf(splitted[1].toLowerCase());
            if (t == null) {
                StringBuilder sb = new StringBuilder("whoslast [type] where type can be:  ");
                for (MapleSquadType z : MapleSquadType.values()) {
                    sb.append(z.name()).append(", ");
                }
                c.getPlayer().dropMessage(6, sb.toString().substring(0, sb.length() - 2));
                return 0;
            }
            if (t.queuedPlayers.get(c.getChannel()) == null) {
                c.getPlayer().dropMessage(6, "The queue has not been initialized in this channel yet.");
                return 0;
            }
            c.getPlayer().dropMessage(6, "Queued players: " + t.queuedPlayers.get(c.getChannel()).size());
            StringBuilder sb = new StringBuilder("List of participants:  ");
            for (Pair<String, String> z : t.queuedPlayers.get(c.getChannel())) {
                sb.append(z.left).append('(').append(z.right).append(')').append(", ");
            }
            c.getPlayer().dropMessage(6, sb.toString().substring(0, sb.length() - 2));
            return 0;
        }
    }

    public static class WhosNext extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                StringBuilder sb = new StringBuilder("whosnext [type] where type can be:  ");
                for (MapleSquadType t : MapleSquadType.values()) {
                    sb.append(t.name()).append(", ");
                }
                c.getPlayer().dropMessage(6, sb.toString().substring(0, sb.length() - 2));
                return 0;
            }
            final MapleSquadType t = MapleSquadType.valueOf(splitted[1].toLowerCase());
            if (t == null) {
                StringBuilder sb = new StringBuilder("whosnext [type] where type can be:  ");
                for (MapleSquadType z : MapleSquadType.values()) {
                    sb.append(z.name()).append(", ");
                }
                c.getPlayer().dropMessage(6, sb.toString().substring(0, sb.length() - 2));
                return 0;
            }
            if (t.queue.get(c.getChannel()) == null) {
                c.getPlayer().dropMessage(6, "The queue has not been initialized in this channel yet.");
                return 0;
            }
            c.getPlayer().dropMessage(6, "Queued players: " + t.queue.get(c.getChannel()).size());
            StringBuilder sb = new StringBuilder("List of participants:  ");
            final long now = System.currentTimeMillis();
            for (Pair<String, Long> z : t.queue.get(c.getChannel())) {
                sb.append(z.left).append('(').append(StringUtil.getReadableMillis(z.right, now)).append(" ago),");
            }
            c.getPlayer().dropMessage(6, sb.toString().substring(0, sb.length() - 2));
            return 0;
        }
    }

    public static class 清怪 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " (範圍:默認全圖) (地圖D:默認當前地圖)");
            }
            MapleMap map = c.getPlayer().getMap();
            double range = Double.POSITIVE_INFINITY;

            if (splitted.length > 1) {
                int irange = Integer.parseInt(splitted[1]);
                if (splitted.length <= 2) {
                    range = irange * irange;
                } else {
                    map = c.getChannelServer().getMapFactory().getMap(Integer.parseInt(splitted[2]));
                }
            }
            if (map == null) {
                c.getPlayer().dropMessage(6, "地圖不存在");
                return 0;
            }
            MapleMonster mob;
            for (MapleMapObject monstermo : map.getMapObjectsInRange(c.getPlayer().getPosition(), range, Arrays.asList(MapleMapObjectType.MONSTER))) {
                mob = (MapleMonster) monstermo;
                if (!mob.getStats().isBoss() || mob.getStats().isPartyBonus() || c.getPlayer().isGM()) {
                    map.killMonster(mob, c.getPlayer(), false, false, (byte) 1);
                }
            }
            return 1;
        }
    }

    public static class 全屏撿物 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            final List<MapleMapObject> items = c.getPlayer().getMap().getMapObjectsInRange(c.getPlayer().getPosition(), GameConstants.maxViewRangeSq(), Arrays.asList(MapleMapObjectType.ITEM));
            MapleMapItem mapitem;
            for (MapleMapObject item : items) {
                mapitem = (MapleMapItem) item;
                if (mapitem.getMeso() > 0) {
                    c.getPlayer().gainMeso(mapitem.getMeso(), true);
                } else if (mapitem.getItem() == null || !MapleInventoryManipulator.addFromDrop(c, mapitem.getItem(), true)) {
                    continue;
                }
                mapitem.setPickedUp(true);
                c.getPlayer().getMap().broadcastMessage(CField.removeItemFromMap(mapitem.getObjectId(), 2, c.getPlayer().getId()), mapitem.getPosition());
                c.getPlayer().getMap().removeMapObject(item);

            }
            return 1;
        }
    }

    public static class 清除BUFF extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            c.getPlayer().cancelAllBuffs();
            return 1;
        }
    }

    public static class 換頻 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            c.getPlayer().changeChannel(Integer.parseInt(splitted[1]));
            return 1;
        }
    }

    public static class Reports extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            List<CheaterData> cheaters = World.getReports();
            for (int x = cheaters.size() - 1; x >= 0; x--) {
                CheaterData cheater = cheaters.get(x);
                c.getPlayer().dropMessage(6, cheater.getInfo());
            }
            return 1;
        }
    }

    public static class ClearReport extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 3) {
                StringBuilder ret = new StringBuilder("report [ign] [all/");
                for (ReportType type : ReportType.values()) {
                    ret.append(type.theId).append('/');
                }
                ret.setLength(ret.length() - 1);
                c.getPlayer().dropMessage(6, ret.append(']').toString());
                return 0;
            }
            final MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(splitted[1]);
            if (victim == null) {
                c.getPlayer().dropMessage(5, "Does not exist");
                return 0;
            }
            final ReportType type = ReportType.getByString(splitted[2]);
            if (type != null) {
                victim.clearReports(type);
            } else {
                victim.clearReports();
            }
            c.getPlayer().dropMessage(5, "Done.");
            return 1;
        }
    }

    public static class 假重載 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            c.getPlayer().fakeRelog();
            return 1;
        }
    }

    public static class 飛 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            SkillFactory.getSkill(1146).getEffect(1).applyTo(c.getPlayer());
            SkillFactory.getSkill(1142).getEffect(1).applyTo(c.getPlayer());
            c.getPlayer().dispelBuff(1146);
            return 1;
        }
    }

    public static class 打開NPC extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <NPCID> (特殊:默認空)");
                return 0;
            }
            NPCScriptManager.getInstance().start(c, Integer.parseInt(splitted[1]), splitted.length > 2 ? StringUtil.joinStringFrom(splitted, 2) : splitted[1]);
            return 1;
        }
    }

    public static class 打開商店 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <商店ID>");
                return 0;
            }
            MapleShopFactory.getInstance().getShop(Integer.parseInt(splitted[1])).sendShop(c);
            return 1;
        }
    }

    public static class 清理掉寶 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            c.getPlayer().getMap().removeDrops();
            return 1;
        }
    }

    public static class 商店 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleShopFactory shop = MapleShopFactory.getInstance();
            int shopId = Integer.parseInt(splitted[1]);
            if (shop.getShop(shopId) != null) {
                shop.getShop(shopId).sendShop(c);
            }
            return 1;
        }
    }

    public static class 殺附近 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleMap map = c.getPlayer().getMap();
            List<MapleMapObject> players = map.getMapObjectsInRange(c.getPlayer().getPosition(), 25000, Arrays.asList(MapleMapObjectType.PLAYER));
            for (MapleMapObject closeplayers : players) {
                MapleCharacter playernear = (MapleCharacter) closeplayers;
                if (playernear.isAlive() && playernear != c.getPlayer() && playernear.getGMLevel() < c.getPlayer().getGMLevel()) {
                    playernear.getStat().setHp((short) 0, playernear);
                    playernear.getStat().setMp((short) 0, playernear);
                    playernear.updateSingleStat(MapleStat.HP, playernear.getStat().getHp());
                    playernear.updateSingleStat(MapleStat.MP, playernear.getStat().getMp());
                    playernear.dropMessage(5, "你太靠近管理員了");
                }
            }
            return 1;
        }
    }

    public static class ManualEvent extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (c.getChannelServer().manualEvent(c.getPlayer())) {
                for (MapleCharacter chrs : c.getChannelServer().getPlayerStorage().getAllCharacters()) {
                    //chrs.dropMessage(0, "MapleGM is hosting an event! Use the @joinevent command to join the event!");
                    //chrs.dropMessage(0, "Event Map: " + c.getPlayer().getMap().getMapName());
                    //World.Broadcast.broadcastMessage(CWvsContext.broadcastMsg(25, 0, "MapleGM is hosting an event! Use the @joinevent command to join the event!"));
                    //World.Broadcast.broadcastMessage(CWvsContext.broadcastMsg(26, 0, "Event Map: " + c.getPlayer().getMap().getMapName()));
                    chrs.getClient().getSession().write(CWvsContext.broadcastMsg(GameConstants.isEventMap(chrs.getMapId()) ? 0 : 25, c.getChannel(), "Event : MapleGM is hosting an event! Use the @joinevent command to join the event!"));
                    chrs.getClient().getSession().write(CWvsContext.broadcastMsg(GameConstants.isEventMap(chrs.getMapId()) ? 0 : 26, c.getChannel(), "Event : Event Channel: " + c.getChannel() + " Event Map: " + c.getPlayer().getMap().getMapName()));
                }
            } else {
                for (MapleCharacter chrs : c.getChannelServer().getPlayerStorage().getAllCharacters()) {
                    //World.Broadcast.broadcastMessage(CWvsContext.broadcastMsg(22, 0, "Enteries to the GM event are closed. The event has began!"));
                    chrs.getClient().getSession().write(CWvsContext.broadcastMsg(GameConstants.isEventMap(chrs.getMapId()) ? 0 : 22, c.getChannel(), "Event : Enteries to the GM event are closed. The event has began!"));
                }
            }
            return 1;
        }
    }

    public static class ActiveBomberman extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleCharacter player = c.getPlayer();
            if (player.getMapId() != 109010100) {
                player.dropMessage(5, "This command is only usable in map 109010100.");
            } else {
                c.getChannelServer().toggleBomberman(c.getPlayer());
                for (MapleCharacter chr : player.getMap().getCharacters()) {
                    if (!chr.isIntern()) {
                        chr.cancelAllBuffs();
                        chr.giveDebuff(MapleDisease.SEAL, MobSkillFactory.getMobSkill(120, 1));
                        //MapleInventoryManipulator.removeById(chr.getClient(), MapleInventoryType.USE, 2100067, chr.getItemQuantity(2100067, false), true, true);
                        //chr.gainItem(2100067, 30);
                        //MapleInventoryManipulator.removeById(chr.getClient(), MapleInventoryType.ETC, 4031868, chr.getItemQuantity(4031868, false), true, true);
                        //chr.gainItem(4031868, (short) 5);
                        //chr.dropMessage(0, "You have been granted 5 jewels(lifes) and 30 bombs.");
                        //chr.dropMessage(0, "Pick up as many bombs and jewels as you can!");
                        //chr.dropMessage(0, "Check inventory for Bomb under use");
                    }
                }
                for (MapleCharacter chrs : c.getChannelServer().getPlayerStorage().getAllCharacters()) {
                    chrs.getClient().getSession().write(CWvsContext.broadcastMsg(GameConstants.isEventMap(chrs.getMapId()) ? 0 : 22, c.getChannel(), "Event : Bomberman event has started!"));
                }
                player.getMap().broadcastMessage(CField.getClock(60));
            }
            return 1;
        }
    }

    public static class DeactiveBomberman extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleCharacter player = c.getPlayer();
            if (player.getMapId() != 109010100) {
                player.dropMessage(5, "This command is only usable in map 109010100.");
            } else {
                c.getChannelServer().toggleBomberman(c.getPlayer());
                int count = 0;
                String winner = "";
                for (MapleCharacter chr : player.getMap().getCharacters()) {
                    if (!chr.isGM()) {
                        if (count == 0) {
                            winner = chr.getName();
                            count++;
                        } else {
                            winner += " , " + chr.getName();
                        }
                    }
                }
                for (MapleCharacter chrs : c.getChannelServer().getPlayerStorage().getAllCharacters()) {
                    chrs.getClient().getSession().write(CWvsContext.broadcastMsg(GameConstants.isEventMap(chrs.getMapId()) ? 0 : 22, c.getChannel(), "Event : Bomberman event has ended! The winners are: " + winner));
                }
            }
            return 1;
        }
    }

    public static class 清理道具 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleCharacter player = c.getPlayer();
            if (splitted.length < 2 || player.hasBlockedInventory()) {
                c.getPlayer().dropMessage(5, splitted[0] + " <道具欄:裝備 / 消耗 / 其他 / 裝飾 / 特殊 / 全部>");
                return 0;
            } else {
                MapleInventoryType type;
                if (splitted[1].equalsIgnoreCase("裝備")) {
                    type = MapleInventoryType.EQUIP;
                } else if (splitted[1].equalsIgnoreCase("消耗")) {
                    type = MapleInventoryType.USE;
                } else if (splitted[1].equalsIgnoreCase("其他")) {
                    type = MapleInventoryType.ETC;
                } else if (splitted[1].equalsIgnoreCase("裝飾")) {
                    type = MapleInventoryType.SETUP;
                } else if (splitted[1].equalsIgnoreCase("特殊")) {
                    type = MapleInventoryType.CASH;
                } else if (splitted[1].equalsIgnoreCase("全部")) {
                    type = null;
                } else {
                    c.getPlayer().dropMessage(5, "找不到道具欄 < 裝備 / 消耗 / 其他 / 裝飾 / 特殊 / 全部>");
                    return 0;
                }
                if (type == null) { //All, a bit hacky, but it's okay 
                    MapleInventoryType[] invs = {MapleInventoryType.EQUIP, MapleInventoryType.USE, MapleInventoryType.SETUP, MapleInventoryType.ETC, MapleInventoryType.CASH};
                    for (MapleInventoryType t : invs) {
                        type = t;
                        MapleInventory inv = c.getPlayer().getInventory(type);
                        byte start = -1;
                        for (byte i = 0; i < inv.getSlotLimit() + 1; i++) {
                            if (inv.getItem(i) != null) {
                                start = i;
                                break;
                            }
                        }
                        if (start == -1) {
                            c.getPlayer().dropMessage(5, "此道具欄沒有道具");
                            return 0;
                        }
                        int end = 0;
                        for (byte i = start; i < inv.getSlotLimit() + 1; i++) {
                            if (inv.getItem(i) != null) {
                                MapleInventoryManipulator.removeFromSlot(c, type, i, inv.getItem(i).getQuantity(), true);
                            } else {
                                end = i;
                                break;//Break at first empty space. 
                            }
                        }
                        c.getPlayer().dropMessage(5, "已清除第" + start + "格到第" + end + "格的道具");
                    }
                } else {
                    MapleInventory inv = c.getPlayer().getInventory(type);
                    byte start = -1;
                    for (byte i = 0; i < inv.getSlotLimit() + 1; i++) {
                        if (inv.getItem(i) != null) {
                            start = i;
                            break;
                        }
                    }
                    if (start == -1) {
                        c.getPlayer().dropMessage(5, "此道具欄沒有道具");
                        return 0;
                    }
                    byte end = 0;
                    for (byte i = start; i < inv.getSlotLimit() + 1; i++) {
                        if (inv.getItem(i) != null) {
                            MapleInventoryManipulator.removeFromSlot(c, type, i, inv.getItem(i).getQuantity(), true);
                        } else {
                            end = i;
                            break;//Break at first empty space. 
                        }
                    }
                    c.getPlayer().dropMessage(5, "已清除第" + start + "格到第" + end + "格的道具");
                }
                return 1;
            }
        }
    }

    public static class Bob extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            MapleMonster mob = MapleLifeFactory.getMonster(9400551);
            for (int i = 0; i < 10; i++) {
                c.getPlayer().getMap().spawnMonsterOnGroundBelow(mob, c.getPlayer().getPosition());
            }
            return 1;
        }
    }

    public static class 殺全圖 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            for (MapleCharacter map : c.getPlayer().getMap().getCharactersThreadsafe()) {
                if (map != null && !map.isIntern()) {
                    map.getStat().setHp((short) 0, map);
                    map.getStat().setMp((short) 0, map);
                    map.updateSingleStat(MapleStat.HP, map.getStat().getHp());
                    map.updateSingleStat(MapleStat.MP, map.getStat().getMp());
                }
            }
            return 1;
        }
    }

    public static class 說話顏色 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <顏色值>");
                return 0;
            }
            try {
                c.getPlayer().setChatType((short) Short.parseShort(splitted[1]));
                c.getPlayer().dropMessage(6, "說話顏色更變完成。");
            } catch (Exception e) {
                c.getPlayer().dropMessage(5, "出現未知錯誤。");
            }
            return 1;
        }
    }

    public static class 檢索指令 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <關鍵字詞>");
                return 0;
            }
            c.getPlayer().dropMessage(6, "檢索指令(關鍵字詞:" + splitted[1] + ")結果如下:");
            HashMap<Integer, ArrayList<String>> commandList = CommandProcessor.getCommandList();
            for (int i = 0; i <= c.getPlayer().getGMLevel(); i++) {
                if (commandList.containsKey(i)) {
                    final PlayerGMRank pGMRank = PlayerGMRank.getByLevel(i);
                    final StringBuilder sb = new StringBuilder("");
                    final StringBuilder 指令前綴 = new StringBuilder("");
                    char[] gmRank = pGMRank.getCommandPrefix();
                    for (int j = 0; j < gmRank.length; j++) {
                        指令前綴.append('"').append(gmRank[j]).append('"');
                        if (j != gmRank.length - 1 && gmRank.length != 1) {
                            指令前綴.append("或");
                        }
                    }
                    for (String s : commandList.get(i)) {
                        if (s.contains(splitted[1].toLowerCase())) {
                            if ((gmRank.length > 1 && s.substring(0, 1).equals(String.valueOf(gmRank[0]))) || gmRank.length == 1) {
                                sb.append(s.substring(1));
                                sb.append("，");
                            }
                        }
                    }
                    if (!sb.toString().equals("")) {
                        c.getPlayer().dropMessage(6, "-----------------------------------------------------------------------------------------");
                        if (pGMRank == PlayerGMRank.NORMAL) {
                            c.getPlayer().dropMessage(6, "玩家指令(前綴:" + 指令前綴 + ")：");
                        } else if (pGMRank == PlayerGMRank.INTERN) {
                            c.getPlayer().dropMessage(6, "實習管理員指令(前綴:" + 指令前綴 + ")：");
                        } else if (pGMRank == PlayerGMRank.GM) {
                            c.getPlayer().dropMessage(6, "遊戲管理員指令(前綴:" + 指令前綴 + ")：");
                        } else if (pGMRank == PlayerGMRank.SUPERGM) {
                            c.getPlayer().dropMessage(6, "高級管理員指令(前綴:" + 指令前綴 + ")：");
                        } else if (pGMRank == PlayerGMRank.ADMIN) {
                            c.getPlayer().dropMessage(6, "伺服器管理指令(前綴:" + 指令前綴 + ")：");
                        }
                        c.getPlayer().dropMessage(6, sb.toString());
                    }
                }
            }
            return 1;
        }
    }

    public static class 全域掉寶 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            c.removeClickedNPC();
            final List<MonsterGlobalDropEntry> drops = MapleMonsterInformationProvider.getInstance().getGlobalDrop();
            StringBuilder name = new StringBuilder();
            if (drops != null && drops.size() > 0) {
                int num = 0;
                int itemId;
                int ch;
                MonsterGlobalDropEntry de;
                for (int i = 0; i < drops.size(); i++) {
                    de = drops.get(i);
                    if (de.chance > 0 && (de.questid <= 0 || (de.questid > 0 && MapleQuest.getInstance(de.questid).getName().length() > 0))) {
                        itemId = de.itemId;
                        if (num == 0) {
                            name.append("全域掉寶數據如下\r\n");
                            name.append("--------------------------------------\r\n");
                        }
                        String namez = "#z" + itemId + "#";
                        if (itemId == 0) { //meso
                            itemId = 4031041; //display sack of cash
                            namez = (de.Minimum * c.getChannelServer().getMesoRate(c.getPlayer().getWorld())) + "到" + (de.Maximum * c.getChannelServer().getMesoRate(c.getPlayer().getWorld())) + "楓幣";
                        }
                        ch = de.chance * c.getChannelServer().getDropRate(c.getPlayer().getWorld());
                        name.append(num + 1).append(") #i").append(itemId).append(":#").append(namez).append("(").append(itemId).append(")").append(de.questid > 0 && MapleQuest.getInstance(de.questid).getName().length() > 0 ? ("[" + MapleQuest.getInstance(de.questid).toString() + "]") : "").append("\r\n掉寶幾率：").append(Integer.valueOf(ch >= 999999 ? 1000000 : ch).doubleValue() / 10000.0).append("%").append(" 來源：").append(de.addFrom).append("\r\n\r\n");
                        num++;
                    }
                }
            }
            if (name.length() > 0) {
                c.getSession().write(NPCPacket.getNPCTalk(9010000, (byte) 0, name.toString(), "00 00", (byte) 0, 9010000));
            } else {
                c.getPlayer().dropMessage(1, "全域掉寶無數據。");
            }
            return 1;
        }
    }

    public static class 製作道具 extends CommandExecute {

        @Override
        public int execute(MapleClient c, String[] splitted) {
            if (splitted.length < 2) {
                c.getPlayer().dropMessage(6, splitted[0] + " <道具ID>");
                return 0;
            }
            final int itemId = Integer.parseInt(splitted[1]);
            final short quantity = (short) CommandProcessorUtil.getOptionalIntArg(splitted, 2, 1);

            if (!c.getPlayer().isAdmin()) {
                for (int i : GameConstants.itemBlock) {
                    if (itemId == i) {
                        c.getPlayer().dropMessage(5, "當前管理員等級沒有製作此道具的權限");
                        return 0;
                    }
                }
            }
            MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
            if (!ii.itemExists(itemId)) {
                c.getPlayer().dropMessage(5, "此道具不存在");
            } else {
                Item item;
                short flag = (short) ItemFlag.LOCK.getValue();

                if (GameConstants.getInventoryType(itemId) == MapleInventoryType.EQUIP) {
                    item = ii.getEquipById(itemId);
                } else {
                    item = new Item(itemId, (byte) 0, quantity, (byte) 0);
                }

                if (ItemConstants.類型.寵物(itemId)) {
                    MaplePet pet = MaplePet.createPet(itemId);
                    if (pet != null) {
                        item.setPet(pet);
                    }
                }
                if (!c.getPlayer().isGM()) {
                    item.setFlag(flag);
                }
                if (!c.getPlayer().isAdmin()) {
                    item.setOwner(c.getPlayer().getName());
                }
                item.setGMLog(c.getPlayer().getName() + " 使用 " + splitted[0] + " 指令制作, 時間:" + FileoutputUtil.CurrentReadable_Time());
                MapleInventoryManipulator.addbyItem(c, item);
            }
            return 1;
        }
    }
}
